import * as fs from 'fs';
import axios from 'axios';
import * as path from 'path';
import { promisify } from 'util';
import FormData from 'form-data';
import { FeishuResponse, Logger, ImportTaskResult } from './types';

const readFileAsync = promisify(fs.readFile);
const renameAsync = promisify(fs.rename);
const statAsync = promisify(fs.stat);

// 飞书配置
const FEISHU_APP_ID = "cli_a750f1d07210d00d";
const FEISHU_APP_SECRET = "KDcAVmk8LhuKc1sQQPEK2baus6PDRQpN";
const FEISHU_WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/your-webhook-url"; // 需要替换为实际的webhook URL
// 不再使用硬编码的token，改为动态获取
// const FEISHU_ACCESS_TOKEN = "u-eoPWiFBi502pAAY9aTlsbXl1n7Jgl5R9Ma001gG020Lb";

// 日志配置
const logger: Logger = {
  info: (message: string): void => {
    console.log(`[INFO] ${new Date().toISOString()} - ${message}`);
    fs.appendFileSync('feishu_bot.log', `[INFO] ${new Date().toISOString()} - ${message}\n`);
  },
  error: (message: string): void => {
    console.error(`[ERROR] ${new Date().toISOString()} - ${message}`);
    fs.appendFileSync('feishu_bot.log', `[ERROR] ${new Date().toISOString()} - ${message}\n`);
  }
};

/**
 * 获取飞书租户访问令牌
 * @returns 访问令牌或null
 */
async function getFeishuTenantAccessToken(): Promise<string | null> {
  try {
    const url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";
    const headers = {
      "Content-Type": "application/json"
    };
    const data = {
      app_id: FEISHU_APP_ID,
      app_secret: FEISHU_APP_SECRET
    };
    
    logger.info(`尝试获取飞书租户访问令牌, app_id: ${FEISHU_APP_ID}`);
    
    try {
      const response = await axios.post<FeishuResponse>(url, data, { headers });
      logger.info(`获取飞书租户访问令牌响应: ${JSON.stringify(response.data)}`);
      
      if (response.data.code === 0) {
        const token = response.data.tenant_access_token || null;
        if (token) {
          logger.info(`成功获取飞书租户访问令牌: ${token}`);
          return token;
        } else {
          logger.error("飞书API返回成功，但未获取到租户访问令牌");
          return null;
        }
      } else {
        logger.error(`获取飞书租户访问令牌失败: 错误码=${response.data.code}, 错误信息=${response.data.msg}`);
        return null;
      }
    } catch (axiosError: any) {
      logger.error(`发送获取租户访问令牌请求异常: ${(axiosError as Error).message}`);
      
      if (axiosError.response) {
        // 服务器返回了错误响应
        logger.error(`服务器响应状态码: ${axiosError.response.status}`);
        logger.error(`服务器响应数据: ${JSON.stringify(axiosError.response.data)}`);
      } else if (axiosError.request) {
        // 请求已发送但没有收到响应
        logger.error("没有收到服务器响应");
      }
      
      return null;
    }
  } catch (error) {
    logger.error(`获取租户访问令牌时发生错误: ${(error as Error).message}`);
    if ((error as any).stack) {
      logger.error(`错误堆栈: ${(error as Error).stack}`);
    }
    return null;
  }
}

/**
 * 上传文件到飞书并获取file_token
 * @param filePath 文件路径
 * @returns file_token或null
 */
async function uploadFileToFeishu(filePath: string): Promise<string | null> {
  try {
    // 获取访问令牌，不再使用硬编码的令牌
    const token = await getFeishuTenantAccessToken();
    if (!token) {
      throw new Error("无法获取飞书访问令牌");
    }
    
    console.log(`成功获取访问令牌: ${token.substring(0, 10)}...`);
    
    // 确保文件名以.md结尾
    let fileName = path.basename(filePath);
    if (!fileName.endsWith('.md')) {
      console.log(`警告: 文件名 ${fileName} 不是.md格式`);
      const newFilePath = `${filePath}.md`;
      await renameAsync(filePath, newFilePath);
      filePath = newFilePath;
      fileName = path.basename(filePath);
      logger.info(`已将文件重命名为: ${fileName}`);
    }
    
    // 上传文件
    const uploadUrl = "https://open.feishu.cn/open-apis/drive/v1/medias/upload_all";
    const headers = {
      "Authorization": `Bearer ${token}`
    };
    
    const fileContent = await readFileAsync(filePath);
    const fileStats = await statAsync(filePath);
    
    const formData = new FormData();
    formData.append('file', fileContent, { filename: fileName, contentType: 'text/markdown' });
    formData.append('file_name', fileName);
    formData.append('parent_type', 'ccm_import_open');
    formData.append('parent_node', 'JJ39fx74clK1mTdlTIbcXPD0nvh');
    formData.append('size', fileStats.size.toString());
    formData.append('extra', JSON.stringify({"obj_type":"docx","file_extension":"md"}));
    
    try {
      const response = await axios.post<FeishuResponse>(uploadUrl, formData, { 
        headers: {
          ...headers,
          ...formData.getHeaders()
        }
      });
      logger.info(`上传文件响应状态码: ${response.status}`);
      logger.info(`上传文件完整响应: ${JSON.stringify(response.data)}`);
      
      if (response.data.code === 0) {
        const fileToken = response.data.data?.file_token;
        if (fileToken) {
          logger.info(`文件上传成功，获取到file_token: ${fileToken}`);
          return fileToken;
        } else {
          logger.error("文件上传成功但未获取到file_token，响应内容: " + JSON.stringify(response.data));
          return null;
        }
      } else {
        logger.error(`上传文件失败，错误码: ${response.data.code}, 错误信息: ${response.data.msg}, 完整响应: ${JSON.stringify(response.data)}`);
        return null;
      }
    } catch (axiosError: any) {
      logger.error(`上传文件请求异常: ${(axiosError as Error).message}`);
      
      if (axiosError.response) {
        // 服务器返回了错误响应
        logger.error(`服务器响应状态码: ${axiosError.response.status}`);
        logger.error(`服务器响应头: ${JSON.stringify(axiosError.response.headers)}`);
        logger.error(`服务器响应数据: ${JSON.stringify(axiosError.response.data)}`);
      } else if (axiosError.request) {
        // 请求已发送但没有收到响应
        logger.error(`没有收到服务器响应: ${axiosError.request}`);
      }
      
      throw axiosError; // 继续抛出以便外层捕获
    }
  } catch (error) {
    logger.error(`上传文件时发生错误: ${(error as Error).message}`);
    if ((error as any).stack) {
      logger.error(`错误堆栈: ${(error as Error).stack}`);
    }
    return null;
  }
}

/**
 * 将上传的markdown文件导入为飞书文档
 * @param fileToken 文件token
 * @param fileName 文件名
 * @returns 文档URL或null
 */
async function importMdToFeishuDoc(fileToken: string, fileName: string = "测试"): Promise<string | null> {
  try {
    // 获取访问令牌，不再使用硬编码的令牌
    const token = await getFeishuTenantAccessToken();
    if (!token) {
      logger.error("无法获取飞书访问令牌");
      throw new Error("无法获取飞书访问令牌");
    }
    
    logger.info(`开始导入文档，fileToken: ${fileToken}, fileName: ${fileName}`);
    
    // 去掉文件名中的星号
    fileName = fileName.replace(/\*/g, '');
    
    // 尝试从fileName中提取项目名称
    // 如果文件名中包含"项目名称："，则提取后面的内容作为项目名
    if (fileName.includes("项目名称：")) {
      const parts = fileName.split("项目名称：");
      if (parts.length > 1 && parts[1].trim()) {
        fileName = parts[1].trim();
        logger.info(`从文件名中提取出项目名称: ${fileName}`);
      }
    }
    
    // 生成带时间戳的文件名
    const currentTime = new Date().toISOString().replace(/[-:]/g, '').replace('T', '_').substring(0, 15);
    const newFileName = `${fileName}_${currentTime}`;
    
    // 导入为飞书文档
    const importUrl = "https://open.feishu.cn/open-apis/drive/v1/import_tasks";
    const headers = {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${token}`
    };
    
    const importData = {
      file_extension: "md",
      file_token: fileToken,
      type: "docx",
      file_name: newFileName,
      point: {
        mount_type: 1,
        mount_key: "JJ39fx74clK1mTdlTIbcXPD0nvh" // 文件夹token
      }
    };
    
    logger.info(`发送导入文档请求: ${JSON.stringify(importData)}`);
    
    try {
      const response = await axios.post<FeishuResponse>(importUrl, importData, { headers });
      logger.info(`导入文档响应: ${JSON.stringify(response.data)}`);
      
      if (response.data.code !== 0) {
        logger.error(`导入文档API返回错误: 错误码=${response.data.code}, 消息=${response.data.msg}`);
        return null;
      }
      
      const ticket = response.data.data?.ticket;
      if (!ticket) {
        logger.error("导入任务创建成功，但未获取到ticket");
        return null;
      }
      
      // 等待任务完成并获取文档URL
      const maxRetries = 5;
      let retryCount = 0;
      let docUrl: string | null = null;
      
      while (retryCount < maxRetries) {
        try {
          // 查询导入任务状态
          const queryUrl = `https://open.feishu.cn/open-apis/drive/v1/import_tasks/${ticket}`;
          logger.info(`查询导入任务状态: ${queryUrl}`);
          
          const queryResponse = await axios.get<FeishuResponse>(queryUrl, { headers });
          logger.info(`查询导入任务状态响应: ${JSON.stringify(queryResponse.data)}`);
          
          // 检查任务是否完成
          if (queryResponse.data.code === 0) {
            const result = queryResponse.data.data?.result as ImportTaskResult | undefined;
            if (!result) {
              logger.error("任务状态响应缺少result字段");
              retryCount++;
              await new Promise(resolve => setTimeout(resolve, 1000));
              continue;
            }
            
            const jobStatus = result.job_status;
            
            if (jobStatus === 0) { // 任务完成
              docUrl = result?.url || null;
              if (docUrl) {
                logger.info(`导入任务完成，文档URL: ${docUrl}`);
                return docUrl;
              } else {
                logger.error("任务完成但未获取到文档URL");
                // 继续查询以尝试获取URL
                await new Promise(resolve => setTimeout(resolve, 1000));
                retryCount++;
                continue;
              }
            } else if (jobStatus === 2) { // 任务失败
              logger.error(`导入任务失败: ${result.job_error_msg || '未知错误'}`);
              // 继续尝试，不要立即break
              await new Promise(resolve => setTimeout(resolve, 1000));
              retryCount++;
              continue;
            } else { // 任务处理中
              logger.info(`导入任务处理中，状态: ${jobStatus}`);
            }
          } else {
            logger.error(`查询任务状态API返回错误: 错误码=${queryResponse.data.code}, 消息=${queryResponse.data.msg}`);
          }
          
          // 如果任务未完成，等待一段时间后重试
          await new Promise(resolve => setTimeout(resolve, 1000));
          retryCount++;
          
        } catch (error) {
          logger.error(`查询导入任务状态时发生错误: ${(error as Error).message}, 堆栈: ${(error as Error).stack}`);
          retryCount++;
          await new Promise(resolve => setTimeout(resolve, 1000));
        }
      }
      
      logger.error("获取文档URL超时或失败");
      return "视频分析完成，但创建文档失败，您仍可以向我提问视频内容的问题";
    } catch (axiosError) {
      logger.error(`发送导入文档请求时发生错误: ${(axiosError as Error).message}, 堆栈: ${(axiosError as Error).stack}`);
      return null;
    }
  } catch (error) {
    logger.error(`导入文件时发生错误: ${(error as Error).message}, 堆栈: ${(error as Error).stack}`);
    return null;
  }
}

/**
 * 上传MD文件到飞书文档
 * @param mdPath MD文件路径
 * @returns 文档URL或null
 */
async function uploadMdToFeishu(mdPath: string): Promise<string | null> {
  try {
    logger.info(`开始上传MD文件到飞书: ${mdPath}`);
    
    // 检查文件是否存在
    if (!fs.existsSync(mdPath)) {
      logger.error(`错误：文件不存在 ${mdPath}`);
      return null;
    }
    
    // 读取文件内容并检查
    const fileContent = fs.readFileSync(mdPath, 'utf8');
    if (!fileContent || fileContent.trim() === '') {
      logger.error(`错误：文件内容为空 ${mdPath}`);
      return null;
    }
    
    // 记录文件内容摘要
    const contentPreview = fileContent.substring(0, 300);
    logger.info(`文件内容开头: ${contentPreview}${fileContent.length > 300 ? '...' : ''}`);
    
    // 获取文件大小
    const fileStats = fs.statSync(mdPath);
    logger.info(`文件大小: ${fileStats.size} 字节`);
    
    // 如果文件内容明确包含"404 Not Found"或错误信息，不要上传
    if (fileContent.includes("404 Not Found") || fileContent.includes("Error:")) {
      logger.error(`文件内容包含错误信息，跳过上传: ${mdPath}`);
      return null;
    }
    
    // 从文件内容中提取项目名称
    const projectName = await getProjectNameFromMd(mdPath);
    logger.info(`从文件内容中提取出项目名称: ${projectName}`);
    
    // 上传文件获取file_token
    logger.info(`开始上传文件获取file_token: ${mdPath}`);
    const fileToken = await uploadFileToFeishu(mdPath);
    if (!fileToken) {
      logger.error(`获取file_token失败，无法继续上传流程，文件路径: ${mdPath}`);
      return null;
    }
    
    logger.info(`成功获取file_token: ${fileToken}，继续导入为飞书文档`);
    
    // 导入为飞书文档，使用提取的项目名称
    const docUrl = await importMdToFeishuDoc(fileToken, projectName);
    if (!docUrl) {
      logger.error(`导入为飞书文档失败，file_token: ${fileToken}, 项目名称: ${projectName}`);
    } else {
      logger.info(`成功导入为飞书文档，URL: ${docUrl}`);
    }
    
    return docUrl;
  } catch (error) {
    logger.error(`上传MD文件异常: ${(error as Error).message}`);
    if ((error as any).stack) {
      logger.error(`错误堆栈: ${(error as Error).stack}`);
    }
    return null;
  }
}

/**
 * 从markdown文件中获取项目名称
 * @param filePath 文件路径
 * @returns 项目名称
 */
async function getProjectNameFromMd(filePath: string): Promise<string> {
  try {
    const content = await readFileAsync(filePath, 'utf-8');
    const lines = content.split('\n');
    for (const line of lines) {
      if (line.includes("项目名称：")) {
        // 获取"项目名称："后面的文字
        const projectName = line.split("项目名称：")[1].trim();
        return projectName;
      }
    }
    return "未命名项目"; // 如果没有找到项目名称，返回默认名称
  } catch (error) {
    console.error(`读取markdown文件时发生错误: ${(error as Error).message}`);
    return "未命名项目";
  }
}

export {
  getFeishuTenantAccessToken,
  uploadFileToFeishu,
  importMdToFeishuDoc,
  uploadMdToFeishu,
  getProjectNameFromMd
}; 